/*
 *	Perlin Production Co. Ltd. September 2012 (c).
 *			bmpcvt.c
 *		Converters for BPP4 images and more
 */
#include "stdio.h"
#include "fdlib.h"
#include "paramlib.h"
#include "WinGDI.h"

#define	_DEBUG	0

#define VRXMAX	32	/* Video-RAM width, bytes */
#define VRYMAX	0x100	/* Video-RAM height, bytes */
#define BPP4	4	/* Image depth */

BPP4Cvt(fdOut,fdIn,_offset,w,h,_rle,_verbose)
FD		*fdOut;
FD		*fdIn;
unsigned	_offset;	/* file offset to pixel data */
unsigned	w;		/* should be less than 0x101 */
unsigned	h;		/* should be less than 0x101 */
unsigned	_rle;		/* RLE (for future extension */
int		_verbose;
{
    unsigned		pos;
    unsigned		sizRow;		/* Number of bytes in a row, 4-128 */
    unsigned		numCol;		/* Number of byte columns in image 1-32 */
    unsigned		plane;
    unsigned		row, column;
    char		pixels[4];	/* 8 pixels to convert to byte below */
    char		*pixel;
    char		bit;
    char		bytes[VRYMAX];	/* Vector video RAM column in plane */
    register char	byte;		/* Vector video RAM column byte */

#if 0	/* uncomment for standalone function usage */
    ChkMax(w, (VRXMAX << 3), "width");
    ChkMax(h, VRYMAX       , "height");
#endif
  
    numCol = (((w*BPP4 + 7)/8) + 3)/4;	/* friggin padding */
    sizRow = numCol << 2;
    
    
#if _DEBUG
    printf("NumCol:%d, SizRow:%d\n",numCol, sizRow);
#endif
    
    for (plane = 1; plane <= 8; plane <<= 1)
    {
	for (column = 0; column < numCol;  ++column ) /* advance by 8 pixels */
	{
		pos = _offset + column * 4;
		
		for	( row = 0
			; row < h	
			; ++row, pos += sizRow
			)
		{
			if (seek(fdIn->file,pos,START) == ERROR)
				trouble("seek failed in", fdIn->name);
								
			/* read 8 pixels of Vector column byte (4 bytes) */
				
			if ((read(fdIn->file, pixels,4)) != 4)
				trouble("read error in",fdIn->name);
				
			
			for 	( byte = 0, bit = 0x80, pixel = pixels
				; bit
				; ++pixel
				)
			{
				if (plane & (*pixel >> 4)) byte |= bit;
				bit >>= 1;
				if (plane & (*pixel & 0xF)) byte |= bit;
				bit >>= 1;
		 	}
		 	bytes[row] = byte;
		}

		/* add column padding in Vector VRAM, bytes */
		for (row = h; row < VRYMAX; ++row) bytes[row] = 0;
		
		if ((write(fdOut->file, bytes,VRYMAX)) != VRYMAX)
			trouble("write error in",fdOut->name);
			
		if (_verbose == VERBMAX) putchar('.');
			
	}
	
	if (numCol < VRXMAX)
	{
		/* add row padding (full columns) in Vector VRAM, bytes */
		setmem (bytes, VRYMAX, 0);
		for (column = numCol; column < VRXMAX; ++column)
		{
		    if ((write(fdOut->file, bytes,VRYMAX)) != VRYMAX)
			trouble("row padding write error in",fdOut->name);
		}
	}
	if (_verbose == VERBMAX) putchar('\n');
    }
}



#if 0

RotPge(_fd, _verbose)
FD	*_fd;
int	_verbose;
{
	char		tmpname	[0x80];	
	char		*s;
	FILE		*tmp;
	int		page,i;
	char		buf[0x100];

	if (_verbose) printf("Rotating video planes in %s\n",_fd->name);

	strncpy(tmpname,_fd->name,0x7F);
	
	if (s=index(tmpname,':')) *++s = 0;
	else *tmpname = 0;
	strcat(tmpname,"TEMPXX.$$$");
	
	if (!mktemp(tmpname)) trouble("generate temporary file name",tmpname);
	
	if ((tmp=creat(tmpname,FCB_WRITE)) == ERROR )
		trouble("creating temporary file",tmpname);
	
	OpenFD(_fd,FCB_READ);
	
	if (_fd->size != 0x8000)
		trouble("file size doesn not match VRAM",_fd->name);
		
	if (_verbose == VERBMAX) printf("Writing temporary %s\n", tmpname);
		

	for ( page=0x6000; page >= 0; page-=0x2000)
	{
		if (seek(_fd->file,page,START) == ERROR)
			trouble("seek error in",_fd->name);
			
		for (i=0; i < 0x20; ++i)
		{
			if ((read(_fd->file, buf,0x100)) != 0x100)
				trouble("read error in",_fd->name);
				
			if ((write(tmp, buf,0x100)) != 0x100)
				trouble("write error in",tmpname);
			if (_verbose == VERBMAX) putchar('.');
		}		
		if (_verbose == VERBMAX) putchar('\n');
	}
	
	if (close(tmp) == ERROR) trouble("closing temporary", tmpname);
	CloseFD(_fd);
	
	if (_verbose == VERBMAX) printf("Renaming to %s\n", _fd->name);
	
	if (unlink(_fd->name) == ERROR ) trouble("deleting", _fd->name);
	if ( rename(_fd->name,tmpname) == ERROR ) trouble("renaming", tmpname);
}

#else


#define SZXBUF 0x100

char	lbuf[SZXBUF];
char	rbuf[SZXBUF];

ExPge(_fd, _l, _r, _verbose)
FD		*_fd;
unsigned	_l;
unsigned	_r;
int		_verbose;
{
	unsigned	l,r,llim;
	
	l = _l * 0x2000;
	r = _r * 0x2000;
	llim = l + 0x2000;

	if (_verbose == VERBMAX) printf("0x%X <-> 0x%X\n",l+0x8000,r+0x8000);
		
	for	( 
		; l < llim 
		; l+=SZXBUF, r+=SZXBUF
		)
	{
		seekrd(_fd,l,lbuf,SZXBUF);
		seekrd(_fd,r,rbuf,SZXBUF);
		
		seekwrt(_fd,l,rbuf,SZXBUF);
		seekwrt(_fd,r,lbuf,SZXBUF);
		
		if (_verbose == VERBMAX) putchar('.');
	}
}



RotPge(_fd, _verbose)
FD	*_fd;
int	_verbose;
{
	if (_verbose) printf("Flipping video planes in %s\n",_fd->name);
	
	OpenFD(_fd,FCB_R_W);
	
	if (_fd->size != 0x8000)
		trouble("file size doesn not match VRAM",_fd->name);
		
	ExPge(_fd, 0, 3, _verbose);
	if (_verbose == VERBMAX) putchar('\n');
	ExPge(_fd, 1, 2, _verbose);
		
	CloseFD(_fd);
}

#endif
